/************************************************************************
 * @file PluginVersion.h
 * @author Ian Chen
 * @version 1.0
 *
 * @section LICENSE
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details at
 * http://www.gnu.org/licenses/lgpl.html
 ************************************************************************/

#ifndef PLUGINVERSION_H
#define PLUGINVERSION_H

#include <plugin/plugin_global.h>

namespace antu
{
namespace plugin
{

#define MAX_MAJOR_VERSION 65535
#define MAX_MINOR_VERSION 65535
#define MAX_PATCH_LEVEL 65535
#define MAX_BUILD_VERSION 65535

#define DEFAULT_MAJOR_VERSION 0
#define DEFAULT_MINOR_VERSION 0
#define DEFAULT_PATCH_LEVEL 0
#define DEFAULT_BUILD_LEVEL 0

//! Object to represent the version of a plugin.
/*! A version object is used to represent the version of a plugin. When
    a plugin depends on other plug-ins to load in a framework, the dependent
    plug-ins' versions are compared to the required version in the plugin
    description information to determine whether the requirement is satisfied.
 */
class PLUGINSHARED_EXPORT PluginVersion
{
private:

    // major version number
    int m_iMajorVersion;

    // minor version number
    int m_iMinorVersion;

    // patch level
    int m_iPatchVersion;

    // build
    int m_iBuild;

public:
    //! Default constructor.
    /*! Instantiates a version object with default version levels.
     */
    PluginVersion();

    //! Constructor
    /*! Constructor that takes a version string.

      \param version Version string
     */
    PluginVersion(const QString& version);

    //! Constructor.
    /*! Constructor that takes four integers as a version.

      \param major Major version level
      \param minor Minor version level
      \param patch Patch version level
      \param build Build level
     */
    explicit PluginVersion(const int major, const int minor = DEFAULT_MINOR_VERSION,
        const int patch = DEFAULT_PATCH_LEVEL, const int build = DEFAULT_BUILD_LEVEL);

    //! Compares two version objects.
    /*! Checks to see if two version objects equal.
      \param version Version object to compare to.
      \return Returns true if two version objects equals, false otherwise.
     */
    inline bool operator==(const PluginVersion& version) const;

    //! Compares two version objects.
    /*! Checks relationship between two version objects.
     \param version Version object to compare to.
     \return Returns true if current version is greater than or equal to
             the object to compare, false otherwise.
     */
    inline bool operator>=(const PluginVersion& version) const;

    //! Major version.
    /*! Major version.
     */
    inline int majorVersion() const
    {
        return this->m_iMajorVersion;
    }

    //! Minor version.
    /*! Minor version.
     */
    inline int minorVersion() const
    {
        return this->m_iMinorVersion;
    }

    //! Patch level.
    /*! Patch level.
     */
    inline int patchLevel() const
    {
        return this->m_iPatchVersion;
    }

    //! Build level.
    /*! Build leve.
     */
    inline int buildLevel() const
    {
        return this->m_iBuild;
    }

    //! Compares two version objects.
    /*! Checks to see if two version objects not equal.

      \param version Version object to compare to.
      \return Returns true if two version objects not equal, false otherwise.
     */
    inline bool operator!=(const PluginVersion& version) const;

    //! Compares two version objects.
    /*! Checks relationship between two version objects.

      \param version Version object to compare to
      \return Returns true if current version is less than or equal to
              the object to compare, false otherwise.
     ***************************************************************************/
    inline bool operator<=(const PluginVersion& version) const;

    //! Compares two version objects.
    /*! Checks relationship between two version objects.

      \param version Version object to compare to.
      \return Returns true if current version is greater than
              the object to compare, false otherwise.
     */
    inline bool operator>(const PluginVersion& version) const;

    //! Checks relationship between two version objects.
    /*! Checks relationship between two version objects.

      \param version Version object to compare to.
      \return Returns true if current version is less than
              the object to compare, false otherwise.
     */
    inline bool operator<(const PluginVersion& version) const;

    //! Copies from another version object.
    /*! Copies from another version object.

      \param version Version object to copy from.
      \return Returns the resulting version object.
     */
    inline PluginVersion& operator=(const PluginVersion& version);

    //! Extracts version information from a string.
    /*! Extracts version information from a string.
      \param versionString String representation of version, should be of format:
                           "a", "a.b", "a.b.c", or "a.b.c.d", where a, b, c, and d should be integer
                           values. If the string is not of the format, default values will be used:
                           major = 1, minor = 0, patch = 0, and build = 0.
      \sa toString()
     */
    static PluginVersion toVersion(const QString& versionString);


    //! Converts Version object to string.
    /*! Converts current version object to its string representation.

      \return Returns string representation of current version object.
      \sa toVersion()
     */
    QString toString() const;
};
}
}

#endif // PLUGINVERSION_H
